This invention relates generally to the field of computer programming language translators and more specifically to compilers and interpreters having object-oriented features.
To cope with the rising complexity of computer programs, many modern programming languages use discrete programming structures called xe2x80x9cobjectsxe2x80x9d that present well-defined interfaces to the outside programming environment and are, in principle, self-contained. Objects typically contain information and methods that operate on the contained information or external information.
The pieces of information associated with an object are referred to as xe2x80x9cpropertiesxe2x80x9d of the object. Each property has a name and can be assigned a value. The type of datum that can be assigned to a property as its value may be, for example, a datum of a simple type, such as an integer or a floating point number, or a datum of a complex type, such as a data structure or another object. When an object is defined, a programmer typically declares the properties that the object contains and specifies the data type for each property. The data type of a property indicates the type of data that the property can represent. For example, a property of the type xe2x80x9cintegerxe2x80x9d can have values 1, 2, 3, etc., whereas a property of the type xe2x80x9cpointer to a methodxe2x80x9d contains a memory address of the beginning of a set of instructions. The properties of an object collectively define its structure.
Each property of an object has associated attributes, such as its name, type, accessibility (e.g., in C++: public, protected, or private), and position within the object. The values of these attributes are not typically accessible to the programmer, i.e., a programmer cannot typically query an object to determine its type or its availability. In C++, a programmer can query the size of a property and could indirectly determine its position within an object by subtracting a pointer to the property from a pointer to the object. The inability to determine attributes of an object further limits programmers from specifying how a program will function.
A method comprises one or more lines of computer code that perform an operation. A method is typically executed by departing from the sequential execution of program lines at the point of the method call, jumping to the lines of code constituting the method, and then returning to the sequential execution of the program below the method call. In object-oriented programming, methods are typically defined as part of a class definition and can be applied only to objects of the defining class, or objects of classes derived from the defining class. The methods that can be applied to an object are collectively called the xe2x80x9cbehaviorxe2x80x9d of the object.
One fundamental goal of object-oriented programming is to encapsulate properties and methods within an object so that a second programmer can use an object defined by a first programmer after learning only the interface of the object. The interface contains code needed to send data to an object and to receive output, such as calculation results, error codes, and object status, from the object. The second programmer should not need to understand the internal workings of the object. Programmers should, therefore, be able to write programs that access objects defined by other programmers and reuse previously defined objects as building blocks of new programs. For example, once a programmer defines an object that represents an automated teller machine, another programmer should be able to use the automated teller machine object in different programs that, for example, model the same automated teller machines in a different banking network. Encapsulation of objects also allows a programmer to modify the internal workings of a particular object to eliminate an error or improve efficiency without having to change other parts of the program that use the object. Encapsulation thus reduces complexity in large programming endeavors.
Another fundamental goal of object-oriented programming is extensibility, i.e., allowing previously created objects to be extended to include additional properties or functionality. This is accomplished by allowing one object to inherit properties and methods from another source, such as a parent object. For example, if a new type of automated teller machine having- additional features becomes available, a programmer should be able to easily create, based upon an existing automated teller machine object, a new automated teller machine object that has additional properties and materials representing the additional features. By eliminating the duplication of programming efforts, inheritance allows existing object-oriented code to be expanded into new uses. Inheritance also facilitates building complex objects from relatively simple building blocks.
The class-instance programming model is one technique for implementing software objects. In the class-instance programming model, abstract objects, known as class objects, are defined, and then instances of the class can be declared. A class object defines the structure and methods of instances of the class, but properties in the abstract class itself do not have values. An instance of a class is an object having the structure defined by the class and capable of being assigned property values. All instances of a class, therefore, have a separate memory structure for storing the property values of that instance. Unlike properties, there is typically only one copy of each of the methods of a class. Method calls, therefore, typically include as an xe2x80x9cinvisible parameterxe2x80x9d an indication of which instance of the class is calling or being passed to the class method.
To facilitate the creation of new classes in the class-instance programming model, a xe2x80x9cchildxe2x80x9d class can be defined that is derived from and inherits the structure of its parent class. An instance of the child class would, therefore, have all the properties and methods defined in the parent class and any additional properties and methods defined specifically in the child class. For example, a class xe2x80x9cVehiclexe2x80x9d may have derived from it a child class xe2x80x9cSpacecraft,xe2x80x9d an instance of which is a particular spacecraft, e.g., the space shuttle Discovery. Because the child class (Spacecraft) is a specific type of the more general parent class (Vehicle), this type of inheritance is known as an xe2x80x9cis-axe2x80x9d inheritance.
To take advantage of inheritance, object-oriented programming languages are often sold with libraries of predefined abstract classes that aid programmers in building new classes and that promote use of standardized objects to build application software. Class libraries theoretically greatly simplify creation of new software.
Many programming languages allow multiple inheritance, i.e., inheriting properties and methods from more than one parent object. For example, FIGS. 1A, 1B, and 1C show, respectively, an xe2x80x9cAirplanexe2x80x9d class 10, a xe2x80x9cBoatxe2x80x9d class 12, and a xe2x80x9cSeaplanexe2x80x9d class 14 that inherits from the Boat and Airplane classes. FIG. 1C shows that the memory structure 16 of an instance of the derived Seaplane class 14 is a concatenation of the memory structures 18 and 20 of Boat class 12 and Airplane class 10, respectively, the concatenation being performed in the order that the inheritance was declared. (The heavy lines of FIGS. 1A, 1B, and 1C enclose the actual memory structures and separate them from label information included in the drawings to facilitate understanding of the prior art and the invention. This convention is also followed in other figures in this specification.) Thus, properties having the same name in multiple parent classes are typically inherited in the children as separate properties. With duplicate method names, however, one method will override another and only one method will be inherited.
Unfortunately, multiple inheritance can cause encapsulation to break down in complex programming environments. One difficulty arises because inheritance lacks granularity, i.e., it is an all-or-nothing proposition. A derived class inherits the entire set of properties and methods of its parent class or classes; a child class cannot inherit only specified properties or methods from individual parents. The following example illustrates the point.
FIG. 2A shows an airplane 24, having an engine 22, a fuselage 26, landing gear 28, wings 30, a rudder 32 and a propeller 34. FIG. 2B shows a boat 36 having a hull 38, a mast 40, a sail 42, an anchor 44, a rudder 46 and riggings 48. In accordance with prior art multiple inheritance, Seaplane class 14 inherits all the properties and methods of Airplane class 10 and Boat class 12, even if some of the properties are redundant or inappropriate for a Seaplane.
FIGS. 2C and 2D illustrate the absurdity of all-or-nothing inheritance. All the components of Boat 36 and Airplane 24 are force-fit into a composite seaplane. FIG. 2C shows a Seaplane 50 that inherited first from Boat 36 and then from Airplane 24. FIG. 2D shows a Seaplane 52 that inherited first from Airplane 24 and then from Boat 36. In both cases, the Seaplane object has some inappropriate properties, such as a Sail 42, and duplicate properties, such as Rudders 32 and 46, Rudder 32 being an aircraft rudder and Rudder 46 being a boat rudder. When a programmer refers to the Rudder property of the Seaplane object, it is unclear which rudder will be referenced.
To avoid some of the absurd results from multiple inheritance and produce a useful derived class, it is sometimes necessary to modify one or more of the parent classes. For example, it may be necessary to change Boat class 12 by eliminating Sail 42 to produce a derived Seaplane class that accurately models a Seaplane. Changing Boat class 12, however, can have consequences in other parts of a program that use objects that inherit properties and methods from the original Boat class 12. For example, a programmer would be required to track down other objects and classes that inherit from the modified Boat class to ensure that other sections of the program are not unintentionally affected. Needing to understand and modify the internal definitions of parent classes is anathema to the concept of encapsulation, which dictates that objects be self-contained so that users of an object need not understand the internal workings of the object. Moreover, changes to a class object in a class library will often require not only recompilation of the library itself, but also recompilation of existing software that uses the changed class object. The problems demonstrated by the foregoing example arise in part because a programmer cannot specify which aspects of a derived class will be inherited from one parent class and which aspects will be inherited from another parent class. A small modification in a parent class may be inappropriate if inherited in all instances of child classes and a modification cannot be made to a single instance if class inheritance is used to provide the change.
If a particular property name or method name appears in more than one parent object, the method that will be inherited and the order of properties in the child class depends upon the order of inheritance and upon arbitration rules. For example, a programmer may wish to define a class E (FIG. 3) that inherits properties and methods from classes C and D, which are defined in two different class libraries, possibly from different software manufacturers. If some of the properties or methods in class A have the same names as properties or methods in class B, the methods and order of properties in classes C and D will depend on the order of inheritance from classes A and B. To function properly, class C may require that a method be inherited from class A, rather than from class B, or that the properties in class C be in a particular order. In the multiple inheritance example of FIG. 3, in which class E inherits from classes C and D, each of which inherits in a different order from classes A and B, it is very difficult to determine the resulting methods and property order in class E. In some cases, class E may be defective because a method inherited from class C may depend upon a property being inherited first from class B, whereas a method inherited from class D may depend upon the same property being inherited first from class A.
Applying arbitration rules to objects having multiple parent classes, each of which can also have multiple parents, can quickly become very complex. The arbitration rules require a detailed knowledge of the structure of the parent classes in the inheritance tree. Because complex classes in class libraries are often built upon simpler classes in the library, a programmer may need to understand the structure of many of the classes in the library before he or she is able to predict how an object he or she creates using class objects from the library will function.
For this reason, programmers that produce class libraries typically provide source code for their class libraries so that applications programmers can determine the inheritance order and redefine classes in the library if necessary. To require knowledge of the parent objects and of complex arbitration rules greatly increases the complexity of object-oriented programming and related source code, vitiates the purpose of encapsulation, and reduces the reusability and extensibility of code. This defeats the purpose of having extensible objects as a result of encapsulation and inheritance and requires extensive knowledge of preexisting class libraries by the programmer.
The complexity and inflexibility of inheritance in languages such as C++ derives in part from the close relationship between the memory structure in which an object is stored and its class definition. As shown in FIG. 1C, a child object is stored in memory as a concatenation of the objects from which it derives. This allows the child object to be xe2x80x9ctype cast,xe2x80x9d i.e., treated as though it were of the same object type as the parent object. Such a system, however, requires that all properties of an object be inherited to maintain the relationship in memory of the different components of a derived object. The rigid memory structure in which properties of objects are stored in the order in which they are declared and inherited also constrains the allocation of memory by a compiler, thereby causing inefficient use of available memory. The compiler is not free to reorder or eliminate duplicate properties when such reordering or elimination of duplication would produce more efficient memory usage.
The object programming model is another technique for implementing software objects. In the object programming model, objects are defined and can then be copied or used to derive other objects. This technique differs from the class-instance model in that there are no abstract classes. In some respects, the object model is more flexible because objects are independent entities and can be created and modified independently of any definition of abstract classes. Moreover, methods can be attached to individual objects, rather than to all members of a class. The object model is also consistent with the use of visual programming tools, such as Microsoft""s Visual Basic(trademark), to create graphical user interfaces. In using such tools, programmers can create, for example, menu objects on the screen, without having to first create an abstract menu class.
In the object model, objects can be created by copying them from other objects, but there are no links between the original object and the newly created object which receives the defined structure and assigned property values from the original object. Property values in the new object do not change when property of the original is changed. Visual Basic(trademark), Asymetrix""s Toolbook(trademark), and Apple""s Hypercard(trademark) are examples of applications based upon an object model without is-a inheritance.
A variation on the object programming model, the object-prototype programming model, provides for inheritance. When the value of a property of a parent object changes, the corresponding property in the child object also changes. A child object in the object-prototype model inherits from a particular parent object, rather than from an abstract class as in class-instance model inheritance, thereby allowing an object to inherit actual property values, in addition to structure. As in the class-instance model, inheritance in the object-prototype model is typically based upon an is-a hierarchy, i.e., a derived object is a type of the parent object. Applications using the object-prototype models are not in widespread commercial use.
Another approach to object-oriented language architecture is the use of a containment, or xe2x80x9chas-a,xe2x80x9d hierarchy as opposed to an is-a hierarchy. In a containment hierarchy, a child object is contained in a parent object, instead of being a type of the parent object. An object is contained within only a single container, although the parent container can itself be contained within another container.
Most implementations do not allow inheritance from the parent in a container hierarchy. In some applications, such as Hypercard(trademark) and Toolbook(trademark), when a method cannot be found associated with an object, the container of the object is checked to determine whether the container defines the method. Such a technique can be considered inheritance of methods from a parent container.
In summary, the class-instance programming model uses abstract classes that define a structure and methods. The structure and methods of one or more abstract classes can be inherited by a child abstract class. Inheritance in the class-instance model is based upon an is-a hierarchy, in which child classes are a type of the parent class and a child class inherits everything in its parent class or classes. Instances, which include property values, are created from the abstract classes, but instances cannot be derived from other instances. Therefore, structure and methods can be inherited, but property values cannot be. This restricts reusability and makes the programmer""s task more complex. Expert knowledge of complex rules of arbitration and of the parent classes are often required to create specific child classes and to understand inherited behavior.
In the object programming model, objects can be copied from other objects, so structure, behavior, and data can be derived. Object systems allow copying of objects, but do not provide for inheritance. Object-prototypes systems provide for inheritance, with the inheritance hierarchies based upon is-a relationships in which each child is a type of the parent. In some applications, limited inheritance of methods is based upon has-a relationships, in which each child is contained in the parent. Has-a inheritance relationships are generally inconsistent with inheritance of property values.
Although the mission of object-oriented programming is to create modular applications using reusable and extensible objects, this promise remains largely unfulfilled in standard object-oriented programming. Classical object-oriented programming is hampered by the complexity of native object classes adopted by programming languages (such as C++), which complexity results in well-known problems in object definition and encapsulation and the related difficulty in dynamically changing objects and methods during application run-time.
Recognizing problems with multiple inheritance in the standard object-oriented language architecture, the prior art takes several approaches to programming unique objects, including binding objects at run-time, modifying and recompiling parent class libraries, and writing custom code to override the inherited properties or methods and assert the class membership of a branch object instead of letting the program architecture determine inheritance. The properties and behavior of an object, however, become dependent on its parent classes and its custom coding, thereby causing difficulty in determining how the object will behave. Complexity of the program architecture increases. The apparent solutions treat only the symptoms and produce further difficulties of their own, making it difficult to create code that is reusable and extensible by other developers.
As a result, current object-oriented programming systems require knowledge of complex rules for arbitrating inheritance and require that a programmer learn entire native class libraries to obtain consistent behavior from objects, determine inheritance, and debug code.
An object of the present invention is, therefore, to provide a programming language system that allows for improved methods of encapsulation and multiple inheritance.
An advantage of this invention is that it can provide such a system in which the behavior of objects can be determined from the objects themselves without resort to their inheritance hierarchy.
Another advantage of this invention is that it can provide for selective inheritance of properties from a parent object or of different properties from different parent objects.
A further advantage of the invention is that it can provide for inheritance of properties based upon the container or containers in which an object is placed.
Still another advantage of this invention is that it can provide for object behavior that is limited to objects whose properties have specified values.
The present invention constitutes a novel computer-implemented system for organizing, storing, and processing data. The system of the present invention simplifies conventional object-oriented programming, thereby increasing programmer efficiency and facilitating the implementation of complex programming models. This has application in fields, such as information management, graphics presentation, and networking, in which the objects that operate together are complex and not easily accessible to the programmer.
The system is based upon an object-prototype model. According to the present invention, an object is defined as a set of properties, which set defines the xe2x80x9cshapexe2x80x9d of the object. Behavior is defined independently of objects and is also defined in association with a particular set of properties, which set defines the xe2x80x9cshapexe2x80x9d of the behavior. Behavior can be applied to objects that have the same shape as the behavior or to objects that have shapes that are convertible to the shape of the behavior. A first shape is convertible to a second shape if the properties comprising the first shape are a superset of the properties comprising the second shape. The applicability of behavior can be further restricted to objects that meet criteria specified by a programmer, such as objects having specified property values or objects that occupy a specified place in a containment hierarchy.
Thus, unlike typical object-oriented programming models, behavior is not defined as member functions of a class of objects or in association with particular objects: A method can be applied to any object that includes the properties to which the method applies. Such a model is analogous to real world systems, in which behavior, such as acceleration caused by gravity, applies to any object that has the appropriate property, i.e., mass, regardless of how the object was derived.
In a preferred embodiment, property names are unique within an application and are listed in an indexed property name table, which provides a property name table index number for each property name and a canonical order for listing properties that comprise any shape. A shape table is maintained that includes entries listing the properties corresponding to each unique object shape and a list of other shapes to which each entry can be converted. An index into the shape table is included in part of the memory structure for each object. The shape table is used to indicate the position of properties within each object and, in some embodiments, to provide a means for converting between shapes.
When a method is called to operate on an object, the method tests the object to determine whether it is of the proper shape or whether it can be converted to the proper shape. If the shape of the object is acceptable, the method tests the object to determine whether it satisfies restrictions, if any, placed on the method, such as requiring that a property of the object have a specified value. If the object passes the tests, it is executed.
Another aspect of the present invention allows different properties of an object to be declaratively inherited from different parent objects. A set of properties within an object can be grouped together and treated as a specific aspect of the object. Such an aspect will be referred to as a Facet(trademark)-type property subgroup. Different Facet(trademark)-type property subgroups of the object can be inherited from different parent objects. Inheritance of a property within a Facet(trademark)-type property subgroup can be based upon an is-a or has-a relationship. Property values inherited based upon an is-a relationship are independent of the location of the object, and the parent of each Facet(trademark)-type property subgroup is determined by declaration. Property values inherited based upon a has-a relationship will derive from the parent object or objects in which the child object is placed.
An object may be placed in more than one container parent, with properties within each of the Facet(trademark)-type property subgroups of the object being inherited from a different one of its parent containers. The parent from which each Facet(trademark)-type property subgroup can be specified. Alternatively, when a child object is contained in multiple parents, each child object Facet(trademark)-type property subgroup is inherited from the parent in which the child object is contained in a parent object Facet(trademark)-type property subgroup having the same name as the child object Facet(trademark)-type property subgroup. Individual properties within a Facet(trademark)-type property subgroup can be declared as inherited or not inherited. The values of properties that are not inherited will be independent of the property values in the parent object. Thus, the properties that a child object inherits is controlled by the child object itself: by its place in a container object and by declaration in the child of which properties are inherited from the parent.
By specifying inheritance at the level of Facet(trademark)-type property subgroups and individual properties, a programmer can define an object to behave the way he or she wants; the properties and behavior of an object will not depend on arbitration rules operating on complex multiple inheritance hierarchies. A programmer can understand the properties and behavior of an object by looking at its declaration without having to understand the complete class library upon which it is based. The present invention thus greatly improves encapsulation in object-oriented programming.
As a further advantage, the shape of an object, which determines which methods can be applied to the object, is not restricted by Facet(trademark)-type property subgroup boundaries. A method, therefore, will apply to any object having specific properties, although the properties reside in different Facet(trademark)-type property subgroups and can be inherited from different parents.
The memory structure of an object of the present invention is independent of the order of properties in the object declaration. This independence provides flexibility to a compiler in allocating memory and frees the compiler to perform optimizations that were heretofore impractical. For example, the compiler can share memory structures among different objects, such as a parent and child objects. Declarations may be constructed using indexing, linked or nested lists, or such other data memory constructs appropriate to optimize compilation.
By utilizing shapes to allow a programmer to control the applicability of methods and Facet(trademark)-type property subgroups to allow a programmer to control inheritance, the method and object implementation engine of present invention provide a programmer with multiple viewpoints of a software object and eliminates ambiguities in manipulating the objects from a particular point of view. The invention thus provides a uniquely extensible, scalable application development architecture that is widely applicable to programming applications that use objects. Applicants use the term xe2x80x9cobjectxe2x80x9d term to apply generally to any software construct having properties and behavior, and the invention is not limited to constructs that fit the formal definition of an object as defined in any particular system.
Additional objects and advantages of the present invention will be apparent from the following detailed description of a preferred embodiment thereof, which proceeds with reference to the accompanying drawings.